package com.github.caijh.mall.wechat.service.impl;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.caijh.commons.util.Asserts;
import com.github.caijh.commons.util.Collections;
import com.github.caijh.commons.util.HttpClientUtils;
import com.github.caijh.commons.util.Images;
import com.github.caijh.commons.util.Strings;
import com.github.caijh.framework.core.exception.BizException;
import com.github.caijh.framework.data.redis.Redis;
import com.github.caijh.framework.log.util.LogUtils;
import com.github.caijh.framework.wechat.enums.WechatType;
import com.github.caijh.framework.wechat.model.AccessToken;
import com.github.caijh.framework.wechat.model.WechatApp;
import com.github.caijh.framework.wechat.model.WechatJsSdkConfig;
import com.github.caijh.framework.wechat.model.WechatMiniLoginRespBody;
import com.github.caijh.framework.wechat.model.WechatUserInfo;
import com.github.caijh.framework.wechat.service.WechatApis;
import com.github.caijh.mall.common.MessageConstants;
import com.github.caijh.mall.constants.Constants;
import com.github.caijh.mall.constants.WeChatConstants;
import com.github.caijh.mall.exception.CrmebException;
import com.github.caijh.mall.front.response.UserRechargePaymentResponse;
import com.github.caijh.mall.payment.vo.wechat.CreateOrderResponseVo;
import com.github.caijh.mall.system.service.SystemConfigService;
import com.github.caijh.mall.utils.RestTemplateUtil;
import com.github.caijh.mall.utils.Utils;
import com.github.caijh.mall.wechat.response.WeChatAuthorizeLoginGetOpenIdResponse;
import com.github.caijh.mall.wechat.service.WeChatService;
import com.github.caijh.mall.wechat.vo.ProgramAddMyTempVo;
import com.github.caijh.mall.wechat.vo.ProgramCategoryVo;
import com.github.caijh.mall.wechat.vo.ProgramTempKeywordsVo;
import com.github.caijh.mall.wechat.vo.ProgramTempVo;
import com.github.caijh.mall.wechat.vo.TemplateMessageVo;
import okhttp3.MediaType;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;


@Service
public class WeChatServiceImpl implements WeChatService {

    private static final Logger logger = LogUtils.getLogger(WeChatServiceImpl.class);

    @Inject
    private Redis redis;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private RestTemplateUtil restTemplateUtil;

    @Value("${server.wechat-js-api-debug}")
    private Boolean debug;

    @Value("${server.wechat-js-api-beta}")
    private Boolean beta;

    @Inject
    private WechatApis wechatApis;

    /**
     * 获取jsApiTicket
     *
     * @return String
     * @author Mr.Zhang
     * @since 2020-06-22
     */
    private String getJsApiTicket() {
        String key = WeChatConstants.REDIS_PUBLIC_JS_API_TICKET;
        String ticket = redis.get(key);
        if (ticket != null && !ticket.equals("")) {
            return ticket;
        }

        String url = getUrl(WeChatConstants.PUBLIC_API_JS_API_TICKET);
        JSONObject jsonObject = get(url + "&type=jsapi");
        ticket = jsonObject.getString("ticket");
        redis.set(key, ticket, WeChatConstants.REDIS_PUBLIC_JS_API_TICKET_EXPRESS);
        return ticket;
    }


    private String getToken() {
        String token = redis.get(WeChatConstants.REDIS_TOKEN_KEY);
        if (token != null) {
            return token;
        }
        AccessToken accessToken = getWechatAccessToken();
        token = accessToken.getToken();
        redis.set(WeChatConstants.REDIS_TOKEN_KEY, token, (long) (accessToken.getExpiresIn() - 100));
        return token;
    }


    /**
     * 获取token
     *
     * @return AccessToken
     */
    private AccessToken getWechatAccessToken() {
        WechatApp wechatApp = getWechatApp();
        return getAccessToken(wechatApp);

    }

    private String getWechatMiniAppToken() {
        String token = redis.get(WeChatConstants.REDIS_WECHAT_MINI_APP_TOKEN_KEY);
        if (token != null) {
            return token;
        }
        AccessToken accessToken = getWechatMiniAccessToken();
        token = accessToken.getToken();
        //存入redis
        redis.set(WeChatConstants.REDIS_WECHAT_MINI_APP_TOKEN_KEY, token, (long) (accessToken.getExpiresIn() - 100));
        return token;
    }

    private AccessToken getWechatMiniAccessToken() {
        WechatApp wechatApp = getWechatMiniApp();
        return getAccessToken(wechatApp);
    }

    private AccessToken getAccessToken(@NonNull WechatApp wechatApp) {
        return wechatApis.getAccessToken(wechatApp);
    }

    private String getApiBaseUrl() {
        return WeChatConstants.API_URL;
    }

    private String getUrl(String uri) {
        String token = getToken();
        return getApiBaseUrl() + uri + "?access_token=" + token;
    }

    private String getWechatMiniFullUrl(String uri) {
        return getApiBaseUrl() + uri + "?access_token=" + getWechatMiniAppToken();
    }

    /**
     * 获取appInfo配置信息
     *
     * @return WechatApp
     */
    private WechatApp getWechatApp() {
        String appId = systemConfigService.getValueByKey(WeChatConstants.WECHAT_APP_ID);
        String secret = systemConfigService.getValueByKey(WeChatConstants.WECHAT_APP_SECRET);

        if (StringUtils.isBlank(appId)) {
            throw new CrmebException("微信appId未设置");
        }

        if (StringUtils.isBlank(secret)) {
            throw new CrmebException("微信secret未设置");
        }
        return new WechatApp(appId, secret, WechatType.PUBLIC);
    }

    private WechatApp getWechatMiniApp() {
        String appId = systemConfigService.getValueByKey(WeChatConstants.WECHAT_MINI_APP_ID);
        String secret = systemConfigService.getValueByKey(WeChatConstants.WECHAT_MINI_APP_SECRET);

        Asserts.isTrue(!StringUtils.isBlank(appId), () -> BizException.of(MessageConstants.WECHAT_MINI_APP_ID_NOT_FOUND));
        Asserts.isTrue(!StringUtils.isBlank(secret), () -> BizException.of(MessageConstants.WECHAT_MINI_APP_SECRET_NOT_FOUND));

        WechatApp wechatApp = new WechatApp(appId, secret, WechatType.MINI);
        wechatApp.setType(WechatType.MINI);
        return wechatApp;
    }


    /**
     * post 请求接口
     *
     * @param url  请求url
     * @param data json格式参数
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    private JSONObject post(String url, String data) {
        logger.info("WeChatServiceImpl.post url: {}, data: {}", url, data);

        JSONObject jsonObject = HttpClientUtils.post(url, null, MediaType.get("application/json;charset=UTF-8"), data, JSON::parseObject);
        return checkResult(jsonObject);
    }

    private JSONObject post(String url, HashMap<String, Object> data) {
        try {
            String json = new JSONObject(data).toJSONString();
            return this.post(url, json);
        } catch (Exception e) {
            throw new CrmebException(e.getMessage());
        }
    }

    /**
     * post 请求接口
     *
     * @param url  请求url
     * @param data json格式参数
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    private String postReturnBuffer(String url, HashMap<String, Object> data) {
        try {
            byte[] bytes = restTemplateUtil.postJsonDataAndReturnBuffer(url, new JSONObject(data));
            String response = new String(bytes);
            if (StringUtils.contains(response, "errcode")) {
                logger.error("微信生成二维码异常" + response);
                throw new CrmebException("微信生成二维码异常");
            }
            return Images.INSTANCE.appendImageSchema(Base64.encodeBase64String(bytes));

        } catch (Exception e) {
            throw new CrmebException(e.getMessage());
        }

    }


    private JSONObject get(String url) {
        try {
            JSONObject result = HttpClientUtils.get(url, JSON::parseObject);
            return checkResult(result);
        } catch (Exception e) {
            throw new CrmebException(e.getMessage());
        }

    }

    /**
     * 获取菜单
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject get() {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_GET_URI);
        return get(url);
    }

    /**
     * 检测结构请求返回的数据
     *
     * @param result 接口返回的结果
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    private JSONObject checkResult(JSONObject result) {

        if (result.equals("")) {
            throw new CrmebException("微信平台接口异常，没任何数据返回！");
        }


        if (result.containsKey("errcode") && result.getString("errcode").equals("0")) {
            return result;
        }

        if (result.containsKey("errmsg")) {
            throw new CrmebException("微信接口调用失败：" + result.getString("errcode") + result.getString("errmsg"));
        }

        return result;
    }

    /**
     * 创建菜单
     *
     * @param data 菜单数据
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject create(String data) {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_CREATE_URI);
        return post(url, data);
    }

    /**
     * 使用接口创建自定义菜单后，开发者还可使用接口删除当前使用的自定义菜单。另请注意，在个性化菜单时，调用此接口会删除默认菜单及全部个性化菜单。
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject delete() {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_DELETE_URI);
        return get(url);
    }

    /**
     * 自定义菜单，获取。
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject getSelf() {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_SELF_SET_URI);
        return get(url);
    }

    /**
     * 自定义菜单，创建。
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject createSelf(String data) {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_ADD_CONDITIONAL_URI);
        return post(url, data);
    }

    /**
     * 自定义菜单，删除。
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject deleteSelf(String menuId) {
        String url = getUrl(WeChatConstants.PUBLIC_API_MENU_ADD_CONDITIONAL_URI);
        return post(url, "{menuid:" + menuId + "}");
    }

    /**
     * 公众号图文消息推送
     *
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Async
    @Override
    public void pushKfMessage(HashMap<String, Object> map) {
        String url = getUrl(WeChatConstants.PUBLIC_API_KF_MESSAGE_SEND);
        post(url, map);
    }

    /**
     * 用户管理 创建标签
     *
     * @param name 标签名
     * @return JSONObject {"tag":{"id":134,//标签id "name":"广东"}}
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject createTags(String name) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_CREATE_URI);
        return post(url, "{\"tag\":{\"name\":\"" + name + "\"}}");
    }

    /**
     * 用户管理 获取标签列表
     *
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject getTagsList() {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_LIST_URI);
        return get(url);
    }

    /**
     * 用户管理 修改标签
     *
     * @param name 标签名
     * @param id   标签id
     * @return JSONObject {"errcode":0,"errmsg":"ok" }
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject updateTags(String id, String name) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_CREATE_URI);
        return post(url, "{\"tag\":{\"id\":" + id + ",\"name\":\"" + name + "\"}}");
    }

    /**
     * 用户管理 删除标签
     *
     * @param id 标签id
     * @return JSONObject {"errcode":0,"errmsg":"ok" }
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject deleteTags(String id) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_DELETE_URI);
        return post(url, "{\"tag\":{\"id\":" + id + "}}");
    }

    /**
     * 用户管理 获取标签下粉丝列表
     *
     * @param id         标签id
     * @param nextOpenId 第一个拉取的OPENID，不填默认从头开始拉取
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject getUserListByTagsId(String id, String nextOpenId) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_USER_GET_URI);
        HashMap<String, Object> map = new HashMap<>();
        map.put("tagid", id);
        map.put("next_openid", nextOpenId);
        return post(url, map);
    }

    /**
     * 用户管理 批量为用户取消标签
     *
     * @param id   标签id
     * @param data 粉丝list
     * @return JSONObject {"errcode":0,"errmsg":"ok" }
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject memberBatchTags(String id, String data) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_MEMBER_BATCH_URI);
        HashMap<String, Object> map = new HashMap<>();
        map.put("openid_list", Strings.toListByComma(data));
        map.put("tagid", id);
        return post(url, map);
    }

    /**
     * 用户管理 批量为用户取消标签
     *
     * @param id   标签id
     * @param data 粉丝list
     * @return JSONObject {"errcode":0,"errmsg":"ok" }
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject memberBatchUnTags(String id, String data) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_MEMBER_BATCH_UN_URI);
        HashMap<String, Object> map = new HashMap<>();
        map.put("openid_list", Strings.toListByComma(data));
        map.put("tagid", id);
        return post(url, map);
    }

    /**
     * 用户管理 获取用户身上的标签列表
     *
     * @param openId 用户身份id
     * @return JSONObject
     * @author Mr.Zhang
     * @since 2020-04-22
     */
    @Override
    public JSONObject getTagsListByUserId(String openId) {
        String url = getUrl(WeChatConstants.PUBLIC_API_TAG_GET_ID_LIST_URI);
        HashMap<String, Object> map = new HashMap<>();
        map.put("openid", openId);
        return post(url, map);
    }

    /**
     * 获取授权页面跳转地址
     *
     * @return authorize url
     */
    @Override
    public String getAuthorizeUrl() {
        WechatApp wechatApp = getWechatApp();
        String redirectUri = systemConfigService.getValueByKeyException(Constants.CONFIG_KEY_SITE_URL) + WeChatConstants.WE_CHAT_AUTHORIZE_REDIRECT_URI_URL;
        return WeChatConstants.WE_CHAT_AUTHORIZE_URL.replace("{$appId}", wechatApp.getAppId()).replace("{$redirectUri}", redirectUri);
    }

    /**
     * 通过code获取获取公众号授权信息
     *
     * @return WeChatAuthorizeLoginGetOpenIdResponse
     */
    @Override
    public WeChatAuthorizeLoginGetOpenIdResponse authorizeLogin(String code) {
        try {
            WechatApp wechatApp = getWechatApp();
            String url = getApiBaseUrl() + WeChatConstants.WE_CHAT_AUTHORIZE_GET_OPEN_ID
                    + "?appid=" + wechatApp.getAppId()
                    + "&secret=" + wechatApp.getSecret()
                    + "&code=" + code
                    + "&grant_type=authorization_code";
            JSONObject result = get(url);
            return JSON.parseObject(result.toJSONString(), WeChatAuthorizeLoginGetOpenIdResponse.class);
        } catch (Exception e) {
            throw new CrmebException(e.getMessage());
        }
    }

    @Override
    public WechatMiniLoginRespBody loginByWechatMini(String code) {
        WechatApp wechatApp = this.getWechatMiniApp();
        String respBody = wechatApis.login(wechatApp, code);
        logger.info("wechat login response boyd {}", respBody);

        return JSON.parseObject(respBody, WechatMiniLoginRespBody.class);
    }

    @Override
    public String qrCode(String page, String uri) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("scene", uri);
        map.put("page", page);
        map.put("width", 200);
        return postReturnBuffer(getWechatMiniFullUrl(WeChatConstants.WE_CHAT_CREATE_QRCODE), map);
    }

    @Override
    public UserRechargePaymentResponse response(CreateOrderResponseVo responseVo) {
        UserRechargePaymentResponse response = new UserRechargePaymentResponse();
        response.setAppId(responseVo.getAppId());
        response.setNonceStr(responseVo.getNonceStr());

        String prepay = "prepay_id=" + responseVo.getPrepayId();

        //构建小程序支付签名
        HashMap<String, Object> map = new HashMap<>();
        map.put("appId", responseVo.getAppId());
        map.put("timeStamp", response.getTimeStamp());
        map.put("nonceStr", response.getNonceStr());
        map.put("package", prepay);
        map.put("signType", response.getSignType());

        //重新计算签名
        response.setPaySign(Utils.getSign(map, systemConfigService.getValueByKey(Constants.CONFIG_KEY_PAY_WE_CHAT_APP_KEY)));

        response.setExtra(prepay);
        response.setPrepayId(responseVo.getPrepayId());
        response.setH5PayUrl(responseVo.getMWebUrl()); //H5支付会有值，否则为null
        return response;
    }

    /**
     * 小程序行业信息
     */
    @Override
    public List<ProgramCategoryVo> getProgramCategory() {
        String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_PROGRAM_CATEGORY);
        JSONObject jsonObject = get(url);
        JSONArray data = jsonObject.getJSONArray("data");
        if (Collections.isEmpty(data)) {
            throw new CrmebException("请先设置小程序行业信息");
        }

        return JSON.parseArray(data.toJSONString(), ProgramCategoryVo.class);
    }

    /**
     * 小程序公共模板库
     *
     * @param page int 页码
     * @return {@code List<ProgramTempVo>}
     * @author Mr.Zhang
     * @since 2020-06-01
     */
    @Override
    public List<ProgramTempVo> getProgramPublicTempList(int page) {

        List<ProgramCategoryVo> programCategory = getProgramCategory();
        String ids = programCategory.stream().map(s -> s.getId().toString()).distinct().collect(Collectors.joining(","));
        String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_PROGRAM_PUBLIC_TEMP);
        int limit = 30;
        int start = (page - Constants.NUM_ONE) * limit;
        JSONObject jsonObject = get(url + "&ids=" + ids + "&start=" + start + "&limit=" + limit);
        JSONArray data = jsonObject.getJSONArray("data");
        if (null == data || data.size() < Constants.NUM_ONE) {
            return null;
        }

        return JSON.parseArray(data.toJSONString(), ProgramTempVo.class);
    }

    /**
     * 小程序公共模板关键词库
     *
     * @param tid 公共模板id
     * @return {@code List<ProgramTempVo>}
     * @author Mr.Zhang
     * @since 2020-06-01
     */
    @Override
    public List<ProgramTempKeywordsVo> getWeChatKeywordsByTid(Integer tid) {
        String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_PROGRAM_PUBLIC_TEMP_KEYWORDS);
        JSONObject jsonObject = get(url + "&tid=" + tid);
        JSONArray data = jsonObject.getJSONArray("data");
        if (null == data || data.isEmpty()) {
            throw new CrmebException("微信没有返回关键词数据");
        }

        return JSON.parseArray(data.toJSONString(), ProgramTempKeywordsVo.class);
    }

    /**
     * 小程序我的模板添加
     *
     * @param programAddMyTempVo ProgramAddMyTempVo 添加我的模板参数
     * @return String 添加至帐号下的模板id，发送小程序订阅消息时所需
     * @author Mr.Zhang
     * @since 2020-06-01
     */
    @Override
    public String programAddMyTemp(ProgramAddMyTempVo programAddMyTempVo) {
        String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_ADD_PROGRAM_TEMPLATE);
        JSONObject data = post(url, JSONObject.toJSONString(programAddMyTempVo));
        if (StringUtils.isBlank(data.getString("priTmplId"))) {
            throw new CrmebException("微信没有返回模板id");
        }

        return data.getString("priTmplId");
    }

    /**
     * 小程序我的模板删除
     *
     * @param myTempId String 我的模板id
     * @author Mr.Zhang
     * @since 2020-06-01
     */
    @Override
    public void programDeleteMyTemp(String myTempId) {
        String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_DELETE_PROGRAM_TEMPLATE);
        HashMap<String, Object> map = new HashMap<>();
        map.put("priTmplId", myTempId);
        post(url, map);
    }


    /**
     * 获取微信用户个人信息
     *
     * @param openId String code换取的 openId
     */
    @Override
    public WechatUserInfo getUserInfo(String openId) {
        WechatApp wechatMiniApp = getWechatMiniApp();
        return wechatApis.getWechatUserInfo(wechatMiniApp, openId);
    }

    /**
     * 获取微信公众号js配置
     *
     * @return WechatJsSdkConfig
     */
    @Override
    public WechatJsSdkConfig getWechatJsSdkConfig(String url) {
        try {
            url = URLDecoder.decode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new CrmebException("url无法解析！");
        }

        WechatApp wechatApp = getWechatApp();
        return wechatApis.getWechatJsSdkConfig(wechatApp, url);
    }


    /**
     * 模板消息发送
     *
     * @return true, if send success
     */
    @Override
    public boolean sendPublicTempMessage(TemplateMessageVo templateMessageVo) {
        try {
            String url = getUrl(WeChatConstants.PUBLIC_API_PUBLIC_TEMPLATE_MESSAGE_SEND);
            post(url, JSON.toJSONString(templateMessageVo));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 订阅消息发送
     *
     * @return true, if send success
     */
    @Override
    public boolean sendProgramTempMessage(TemplateMessageVo templateMessageVo) {
        try {
            String url = getWechatMiniFullUrl(WeChatConstants.PUBLIC_API_PROGRAM_TEMPLATE_MESSAGE_SEND);
            post(url, JSON.toJSONString(templateMessageVo));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 模板消息 行业信息
     *
     * @return {@code List<String>}
     */
    @Override
    public JSONObject getIndustry() {
        try {
            String url = getUrl(WeChatConstants.PUBLIC_API_TEMPLATE_MESSAGE_INDUSTRY);
            return get(url);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取微信素材上传url
     *
     * @return String
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    @Override
    public String getUploadMedia() {
        return getUrl(WeChatConstants.PUBLIC_API_MEDIA_UPLOAD);
    }

    /**
     * 获取微信素材
     *
     * @return String
     * @author Mr.Zhang
     * @since 2020-06-03
     */
    @Override
    public String getMedia() {
        return getUrl(WeChatConstants.PUBLIC_API_MEDIA_GET);
    }

}

